#include "stdafx.h"
#include <stddef.h>
#include "ISort2.h"
#include "RealISort.h"

RealISort::RealISort()
{
}

RealISort::~RealISort()
{
}

HRESULT STDMETHODCALLTYPE RealISort::QueryInterface(REFIID riid, void **ppv)
{
    if (IsEqualIID(riid, IID_IUnknown) ||
        IsEqualIID(riid, IID_ISort))
    {
        *ppv = this;
        AddRef();
        return S_OK;
    }
    else if (IsEqualIID(riid, IID_IConnectionPointContainer))
    {
        *ppv = (unsigned char *)this + offsetof(MyISort, container);
        AddRef();
        return S_OK;
    }
    else
    {
        *ppv = NULL;
        return E_NOINTERFACE;
    }

}

ULONG STDMETHODCALLTYPE RealISort::AddRef()
{
    MyISort *p = (MyISort *)this;
    return ++p->count;
}

ULONG STDMETHODCALLTYPE RealISort::Release()
{
    MyISort *p = (MyISort *)this;
    if (--p->count == 0)
    {
        delete p;
        InterlockedDecrement(&OutstandingObjects);
        return 0;
    }
    return p->count;
}

HRESULT STDMETHODCALLTYPE RealISort::Sort(void *base, DWORD numElems, DWORD sizeElem)
{
    MyISort *p = (MyISort *)this;
    if (p->compare == NULL) return E_FAIL;

    char *hi = (char *)base + (numElems - 1) * sizeElem;
    char *temp = new char[sizeElem];
    if (temp == NULL) return E_OUTOFMEMORY;

    while (hi > base)
    {
        char *m = (char *)base;
        for (char *it = (char *)base + sizeElem; it <= hi; it += sizeElem)
        {
            if (p->compare->Compare(it, m) > 0)
                m = it;
        }
        memcpy(temp, m, sizeElem);
        memcpy(m, hi, sizeElem);
        memcpy(hi, temp, sizeElem);
        hi -= sizeElem;
    }

    delete [] temp;
    return S_OK;
}
